home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
331_01
/
hist.c
< prev
next >
Wrap
Text File
|
1990-06-12
|
8KB
|
298 lines
/*
HEADER: CUG999.11;
TITLE: GED (nee QED) screen editor -- part 2;
DATE: 12/19/86;
DESCRIPTION: "Text changing routines for the GED editor. Eg,
movechar, insertchar.";
SYSTEM: MS-DOS;
FILENAME: GED2.C;
AUTHORS: G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
COMPILERS: DeSmet C;
*/
/*
e/qed/ged screen editor
(C) G. Nigel Gilbert, MICROLOGY, 1981
August-December 1981
Modified: Aug-Dec 1984: BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
March 1985: BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
May 1986: converted to ged - Mel Tearle
FILE: hist.c
FUNCTIONS: undo, pop
PURPOSE: perform text changing commands
*/
#include <stdio.h>
#include <ctype.h>
#include "ged.h"
/* undoes edits on current line and then from history
*/
undo()
{
int l, inicnt, c;
puttext();
if ( histcnt == 0 ) {
error( " Nothing to undo " );
return;
}
inicnt = histcnt;
c = OOPSKEY; /* do the first one for free */
do {
vbord1 = MAXINT;
vbord2 = 0;
blocking = NO;
switch (c) {
case OOPSKEY:
case '-': /* ctrl key not requeired */
case '_':
if (histcnt > 0) {
do {
l = undoredo(-1); /* pre decrements histptr */
}
while ( histcnt > 0 && history[histptr].histcomm ==
history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
hshow(l);
}
else {
error("Can't undo more. Redo or escape. Escape obliterates redo.");
}
break;
case '=':
case '+': /* same key */
if (histcnt < inicnt) {
do {
l = undoredo(1); /* post increments histptr */
}
while ( histcnt < inicnt && history[histptr].histcomm ==
history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
hshow(l);
}
else {
error("Can't redo future. Now in edit mode.");
resetpcursor();
while (chkbuf() == 0)
;
goto leave;
}
break;
default:
error("Bad key. ^- to undo more, + or = to redo, <esc> to resume editing");
break;
}
}
while ( (c = getkey()) != ESCKEY);
leave:;
blocking = NO;
putpage();
blankedmess = YES;
return;
}
/* local function */
hshow(l)
int l;
{
int i;
/* leave room for the line number. not an error, but show in reverse field */
hstart(FNPOS);
error1(" - undo, +/= redo; or <esc> ");
show_time(1);
if (vbord2 >= vbord1)
blocking=TRUE;
/* moveline requires that the existing physical display agree with memory.
* They aren't the same at this point if lines within the active display
* area have been changed. A complete rewrite is necessary.
*/
charn = offset + (offset>0);
/* the preferred cursor position is the one that does not cause scrolling */
cursory += l - cline;
/* re-optimize the cursor if the new location is off-screen */
if (cursory > SHEIGHT || cursory < topline)
cursory = topline + (SHEIGHT - topline)/2;
/* but it is more important to see the whole block */
i = cline;
cline = l;
calp();
cline = i;
if (vbord2 >= plast)
cursory += plast - vbord2 -1; /* limit checked in calp() */
plast = -1;
moveline(l-cline);
return;
}
/* --------------------------------------- */
/* local function
* direc = 1 to redo, -1 to undo.
*/
int undoredo(direc)
int direc;
{
int l, hpage, hoff;
if (direc < 0) { /* post increment for redo */
if ( --histptr < 0 )
histptr = ( HISTLEN - 1 );
histcnt--;
}
storehist = NO;
l = history[histptr].histline;
hpage = history[histptr].histp.page;
hoff = history[histptr].histp.moffset;
/* the following comments apply to an undo step. The same code is executed
* for the redo, but then the undo/redo roles change. The function is
* fully symmetrical between redo/undo, and except for a wasted byte
* in the inject() is indefinately reversible.
*/
switch ( history[histptr].histtype ) {
case HISTINSERT:
history[histptr].histp.moffset = tp[l].moffset; /* prepare for redo */
history[histptr].histp.page = tp[l].page; /* prepare for redo */
history[histptr].histtype = HISTDELETE; /* prepare for redo */
deltp(l,1); /* undo */
if (l <= vbord2)
vbord2--;
break;
case HISTDELETE:
inject(l-1,""); /* undo */
tp[l].moffset = hoff; /* undo */
tp[l].page = hpage; /* undo */
history[histptr].histtype = HISTINSERT; /* prepare for redo */
if (vbord2 >= l)
vbord2++;
if (l > vbord2)
vbord2 = l;
if (l < vbord1)
vbord1 = l;
break;
case HISTREPLACE:
history[histptr].histp.moffset = tp[l].moffset; /* prepare for redo */
history[histptr].histp.page = tp[l].page; /* prepare for redo */
tp[l].page = hpage; /* undo */
tp[l].moffset= hoff; /* undo */
if (l > vbord2)
vbord2 = l;
if (l < vbord1)
vbord1 = l;
break;
}
if (direc > 0) {
if (++histptr >= HISTLEN)
histptr = 0;
histcnt++;
}
return l;
}
/* --------------------------------------- */
/* pop the last deleted line from the history buffer.
* This is a prelimenary implementation of stack operations and is
* something of a kludge. The stack needs its own table. It can
* use the text of the lines in the histroy buffer, though.
* This "stack" will be overwritten after 100 editing operations.
* Pops can be undone, so a different area of the data base used here
* is modifed by addhistory() when a pop is performed.
* Editing which occurs later than the pop can be undone without conflict,
* provided there is not too much of it.
*/
pop(mode)
int mode;
{
int onpage; /* flag for changes to current screen */
int l, slot;
int h0, h1, h2;
char *ptr;
char *gethist();
puttext(); /* must be done before the stack test */
if ( stkcnt == 0 ) {
error( " Stack empty " );
return;
}
h0 = stkptr;
h1 = stkcnt;
h2 = 0;
do {
if ( --stkptr < 0 )
stkptr = ( HISTLEN - 1 );
stkcnt--;
ptr = gethist(history[stkptr].histp.page,history[stkptr].histp.moffset);
switch ( history[stkptr].histtype ) {
case HISTREPLACE:
break;
case HISTINSERT:
break;
case HISTDELETE:
h2 = 1;
break;
}
}
while ( !h2 && stkcnt && history[stkptr].histcomm ==
history[( stkptr-1 < 0 ? HISTLEN-1 : stkptr-1) ].histcomm );
if (mode == 1) {
stkptr = h0; /* copy and pop. restore to original state. */
stkcnt = h1;
}
if (!h2)
error( " Stack empty " );
else {
vbord1=cline;
vbord2=cline;
blocking=TRUE;
scrolldown(cursory);
sync(offset + (offset>0));
putline(cline, cursory, ptr);
putlineno(cline); /* new col no */
resetpcursor();
/* do the slow work while waiting for a keystroke, otherwise the next
operation is delayed
*/
inject(cline-1,ptr);
calp(); /* plast may have changed */
while (chkbuf()==0) /* wait for any